package modules

import (
	"github.com/tebeka/selenium"
	"log"
	"github.com/tebeka/selenium/chrome"
	"config"
	"os"
	"time"
	"utils"
	"showSdk/normalRequest"
	"encoding/json"
	"errors"
	"common"
	"fmt"
	"net/http"
)

type LoginAuth struct {
	config           *config.Config
	chromeDriverPath string
	webDriver        selenium.WebDriver
	base64Img        string
}

// 初始化配置
func (l *LoginAuth) InitConfig(config *config.Config) {
	l.config = config
	path, _ := os.Getwd()
	l.chromeDriverPath = path + "/chromedriver"
}

// 结束的时候
func (l *LoginAuth) OnDestroy() {
	if l.webDriver != nil {
		l.webDriver.Quit()
	}
}

// StartChrome 启动谷歌浏览器headless模式
func (l *LoginAuth) StartChrome() error {
	opts := []selenium.ServiceOption{}
	caps := selenium.Capabilities{
		"browserName": "chrome",
	}

	// 禁止加载图片，加快渲染速度
	//imagCaps := map[string]interface{}{
	//	"profile.managed_default_content_settings.images": 2,
	//}

	chromeCaps := chrome.Capabilities{
		//Prefs: imagCaps,
		Path: "",
		Args: []string{
			"--headless", // 设置Chrome无头模式
			"--no-sandbox",
			"--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7", // 模拟user-agent，防反爬
		},
	}
	caps.AddChrome(chromeCaps)
	// 启动chromedriver，端口号可自定义
	_, err := selenium.NewChromeDriverService(l.chromeDriverPath, 1616, opts...)
	if err != nil {
		log.Printf("Error starting the ChromeDriver server: %v", err)
	}
	// 调起chrome浏览器
	webDriver, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", 1616))
	if err != nil {
		return err
	}
	// 这是目标网站留下的坑，不加这个在linux系统中会显示手机网页，每个网站的策略不一样，需要区别处理。
	//webDriver.AddCookie(&selenium.Cookie{
	//	Name:  "defaultJumpDomain",
	//	Value: "www",
	//})
	err = webDriver.SetImplicitWaitTimeout(3e9)
	if err != nil {
		return err
	}
	l.webDriver = webDriver
	return nil
}

// 搜索功能
// Deprecated:
func (l *LoginAuth) Search() {
	err := l.webDriver.Get(l.config.RootUrl) //打开首页
	if err != nil {
		log.Println("错误", err.Error())
	}
	webElement, err := l.webDriver.FindElement(selenium.ByID, "code") //找到搜索框
	if err != nil {
		log.Println("错误", err.Error())
	}
	err = webElement.SendKeys(l.config.SearchCode) //插入搜索码
	if err != nil {
		log.Println("错误", err.Error())
	}
	webElement, err = l.webDriver.FindElement(selenium.ByName, "submit_bt") //找到搜索按钮
	if err != nil {
		log.Println("错误", err.Error())
	}
	err = webElement.Click() //点击搜索
	if err != nil {
		log.Println("错误", err.Error())
	}
	time.Sleep(5e9)
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "/html/body/div[2]/div[2]/div/ul[1]/li[1]/a")
	if err != nil {
		log.Println("错误", err.Error())
	}
	b, err := webElement.IsDisplayed()
	if err != nil {
		log.Println("错误", err.Error())
	}
	if b {
		log.Println("老子进入线路选择页面了")
	}
}

// 首页,会弹出ip地址异常,输入验证
func (l *LoginAuth) Index(retryCount int) error {
	ifRetry := func(mErr error) error {
		if retryCount > 0 {
			return l.Index(retryCount - 1)
		} else {
			return mErr
		}
	}
	err := l.webDriver.Get(l.config.RootUrl) //打开首页
	//l.webDriver.WaitWithTimeout(titleChangeCondition,1*time.Second)
	if err != nil {
		return ifRetry(err)
	}
	time.Sleep(3e9)
	//log.Println(l.webDriver.PageSource())

	code, err := l.verCode("//*[@id=\"img\"]/img")
	if err != nil {
		return ifRetry(err)
	}
	webElement, err := l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"VerifyCode\"]") //找到输入框
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.SendKeys(code)
	if err != nil {
		return ifRetry(err)
	}
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"login_form\"]/div[2]/table/tbody/tr/td[1]/input[3]") //找到按钮
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.Click() //点击按钮
	if err != nil {
		return ifRetry(err)
	}
	time.Sleep(1e9)
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"sec\"]") //找到安全控件
	if err != nil {
		return ifRetry(err)
	}
	nodeTime := time.Now().Unix()
	for {
		b, err := webElement.IsDisplayed()
		if err != nil {
			return ifRetry(err)
		}
		if !b {
			curTime := time.Now().Unix()
			//超时
			if curTime-nodeTime > 3e9 {
				return ifRetry(errors.New("Displaye timeout"))
			}
		} else {
			//登陆页面显示出来了
			break
		}
	}
	return nil
}

// 登陆
func (l *LoginAuth) Login(retryCount int) (error) {
	time.Sleep(2e9)
	ifRetry := func(mErr error) error {
		if retryCount > 0 {
			return l.Login(retryCount - 1)
		} else {
			return mErr
		}
	}
	webElement, err := l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"sec\"]") //找到安全控件
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.Click() //取消安全控件
	if err != nil {
		return ifRetry(err)
	}
	// 账号输入框
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"login_form\"]/table/tbody/tr[1]/td[1]/input") //找到账号输入框
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.SendKeys(l.config.Account)
	if err != nil {
		return ifRetry(err)
	}
	// 密码框
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"password_txt\"]") //找到密码输入框
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.SendKeys(l.config.Password)
	if err != nil {
		return ifRetry(err)
	}
	// 验证码图片
	code, err := l.verCode("//*[@id=\"img\"]/img") //过验证码
	if err != nil {
		return ifRetry(err)
	}
	log.Println("验证码2:", code)
	// 找到验证码输入框
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"login_form\"]/table/tbody/tr[3]/td[1]/input") //找到验证码输入框
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.SendKeys(code)
	if err != nil {
		return ifRetry(err)
	}
	// 登陆按钮
	webElement, err = l.webDriver.FindElement(selenium.ByXPATH, "//*[@id=\"login_form\"]/table/tbody/tr[1]/td[2]/div/input[4]") //找到登陆按钮
	if err != nil {
		return ifRetry(err)
	}
	err = webElement.Click()
	if err != nil {
		return ifRetry(err)
	}
	time.Sleep(1e9)
	return nil
}

func (m *LoginAuth) RefreshCookies() ([]http.Cookie, error) {
	err := m.webDriver.Refresh()
	if err != nil {

	}
	cookies, err := m.webDriver.GetCookies()
	if err != nil {

	}
	var b bool
	for _, cookie := range cookies {
		if cookie.Name == "AC" {
			b = true
		}
	}
	if b {
		httpCookies := common.ConvertCookies(cookies)
		return httpCookies, nil
	}
	return nil, errors.New("Not found cookie with name is AC")

	//var nodeCookies = make(map[string]interface{}, 0)
	//for {
	//	m.webDriver.Refresh()
	//	cookies, err := m.webDriver.GetCookies()
	//	if err != nil {
	//	}
	//	if len(nodeCookies) == 0 {
	//		for _, cookie := range cookies {
	//			log.Println(cookie.Name, cookie.Value)
	//			nodeCookies[cookie.Name+":"+cookie.Value] = cookie
	//		}
	//	} else {
	//		var newCookies = make(map[string]interface{}, 0)
	//		var b bool
	//		for _, cookie := range cookies {
	//			cookieKey := cookie.Name + ":" + cookie.Value
	//			newCookies[cookieKey] = cookie
	//			if _, ok := nodeCookies[cookieKey]; !ok {
	//				b = true
	//			}
	//		}
	//		if b {
	//			for k, _ := range nodeCookies {
	//				log.Println("旧的>", nodeCookies[k])
	//			}
	//			for k, _ := range newCookies {
	//				log.Println("新的>", nodeCookies[k])
	//			}
	//		}
	//	}
	//	time.Sleep(1e9)
	//}
}

// 通过打码平台查询验证码
// base64img
func (m *LoginAuth) remoteVerCode(base64img string) (string, error) {
	//encodeString = strings.Replace(encodeString, "\\", "%2F", -1)
	//encodeString = strings.Replace(encodeString, "/", "%2F", -1)
	//appid he sign
	res := normalRequest.ShowapiRequest(m.config.ReqUrl, m.config.AppId, m.config.Sign)
	res.AddTextPara("img_base64", base64img)
	res.AddTextPara("typeId", "15")
	resp, err := res.Get()
	if err != nil {
		return "", err
	}
	respStruct := struct {
		ShowapiResCode  int    `json:"showapi_res_code"`
		ShowapiResError string `json:"showapi_res_error"`
		ShowapiResBody struct {
			Result string `json:"Result"`
		} `json:"showapi_res_body"`
	}{}
	err = json.Unmarshal([]byte(resp), &respStruct)
	if err != nil {
		return "", err
	}
	if respStruct.ShowapiResError == "" && respStruct.ShowapiResBody.Result != "" {
		log.Println("过验证码:", respStruct.ShowapiResBody.Result)
		return respStruct.ShowapiResBody.Result, nil
	} else {
		log.Println("没钱了", respStruct.ShowapiResError)
	}
	return "", err
}

// 过验证码
func (l *LoginAuth) verCode(xpath string) (string, error) {
	webElement, err := l.webDriver.FindElement(selenium.ByXPATH, xpath) //找到图片
	if err != nil {
		log.Println("错误", err.Error())
	}
	imgBytes, err := l.webDriver.Screenshot() //截屏
	if err != nil {
		log.Println("错误", err.Error())
	}
	size, err := webElement.Size() //获取验证码图片大小
	if err != nil {
		log.Println("错误", err.Error())
	}
	point, err := webElement.Location() //获取验证码图片位置
	if err != nil {
		log.Println("错误", err.Error())
	}
	dpiRate := 2                                                  //2倍的屏幕像素密度
	base64Img := utils.Screenshot(imgBytes, size, point, dpiRate) //截取验证码一块存储到temp2.jpg
	code, err := l.remoteVerCode(base64Img)
	return code, err
}
